package rtdb.pas;

import com.ht.aems.fesmodel.CommUnit;
import com.ht.aems.fesmodel.data.AnalogPoint;
import com.ht.aems.fesmodel.data.DiscretePoint;
import com.ht.aems.fesmodel.data.YCData;
import com.ht.aems.fesmodel.data.YXData;
import org.apache.log4j.Logger;

import java.io.Serializable;
import java.lang.reflect.Field;

/**
 * Created by IntelliJ IDEA.
 * User: Dong Shufeng
 * Date: 11-10-27
 */
public abstract class PasFesPoints implements Serializable {
    private static Logger log = Logger.getLogger(PasFesPoints.class);

    private CommUnit commUnit;
    private Field[] analogs = new Field[0];
    private Field[] discretes = new Field[0];

    protected void initial() {
        int analogMeasNum = 0;
        int discreteMeasNum = 0;
        Field[] fields = this.getClass().getFields();
        for (Field f : fields) {
            if (f.getType() == DiscretePoint.class) {
                discreteMeasNum++;
            } else if (f.getType() == AnalogPoint.class)
                analogMeasNum++;
        }
        Field[] analogs = new Field[analogMeasNum];
        Field[] discretes = new Field[discreteMeasNum];
        int analogIndex = 0;
        int discreteIndex = 0;
        for (Field f : fields) {
            if (f.getType() == DiscretePoint.class) {
                discretes[discreteIndex++] = f;
            } else if (f.getType() == AnalogPoint.class)
                analogs[analogIndex++] = f;
        }
        setAnalogs(analogs);
        setDiscretes(discretes);
    }

    public abstract String getRtuName();

    public abstract String getPointName(String fieldName);

    public abstract int getHistoryType(String fieldName);

    public YCData createYc() {
        //repeat yc data from scada to fes point
        if (getCommUnit() == null) {
            log.debug("No virtual SE rtu is found.");
            return null;
        }
        YCData yc = new YCData();
        yc.setRemoteUnitId(getCommUnit().getId());
        try {
            int[] ycBits = new int[getAnalogs().length];
            double[] ycData = new double[getAnalogs().length];
            int index = 0;
            for (Field f : getAnalogs()) {
                AnalogPoint p = (AnalogPoint) f.get(this);
                ycData[index] = p.getEngValue();
                ycBits[index++] = p.getPointNum();
                if (p.getTimestamp() != null && p.getTimestamp().getTime() > yc.getTimestamp())
                    yc.setTimestamp(p.getTimestamp().getTime());
            }
            yc.setYcBit(ycBits);
            yc.setData(ycData);
            return yc;
        } catch (Exception e) {
            log.warn("Faile to create yc of se measurements:" + e);
            return null;
        }
    }

    public YXData createYx() {
        //repeat yc data from scada to fes point
        if (getCommUnit() == null) {
            log.debug("No virtual SE rtu is found.");
            return null;
        }
        YXData yx = new YXData();
        yx.setRemoteUnitId(getCommUnit().getId());
        try {
            int[] yxBits = new int[getDiscretes().length];
            int[] yxData = new int[getDiscretes().length];
            int index = 0;
            for (Field f : getDiscretes()) {
                DiscretePoint p = (DiscretePoint) f.get(this);
                yxData[index] = p.getEngValue();
                yxBits[index++] = p.getPointNum();
                if (p.getTimestamp() != null && p.getTimestamp().getTime() > yx.getTimestamp())
                    yx.setTimestamp(p.getTimestamp().getTime());
            }
            yx.setYxBit(yxBits);
            yx.setData(yxData);
            return yx;
        } catch (Exception e) {
            log.warn("Faile to create yx of se measurements:" + e);
            return null;
        }
    }


    public CommUnit getCommUnit() {
        return commUnit;
    }

    public void setCommUnit(CommUnit commUnit) {
        this.commUnit = commUnit;
    }

    public Field[] getAnalogs() {
        return analogs;
    }

    public void setAnalogs(Field[] analogs) {
        this.analogs = analogs;
    }

    public Field[] getDiscretes() {
        return discretes;
    }

    public void setDiscretes(Field[] discretes) {
        this.discretes = discretes;
    }
}
